home *** CD-ROM | disk | FTP | other *** search
/ Grand Slam 3 / Grand Slam 3.iso / 026 / imphob10.arj / IMP10_EX.ARJ / W_GEMMIS.ARJ / MEM32IMP.INC < prev   
Text File  |  1995-05-15  |  22KB  |  1,076 lines

  1. ;║ A FLAT REAL MODE INITIALIZER EXAMPLE
  2. ;║ ────────────────────────────────────
  3. ;║
  4. ;║ Compliant with RAW, XMS or EMS environments
  5. ;║
  6. ;║ Documentation used :
  7. ;║ microsoft eXtended Memory Specification (XMS) ver 3.0
  8. ;║ lotus/intel/microsoft Expanded Memory Specification (EMS) ver 4.0
  9. ;║ microsoft undocumented Global EMM Import Specification (GEMMIS) ver 1.11
  10. ;║
  11. ;║ Documentation needed :
  12. ;║ standard method for detecting drivers which use the VDISK allocation scheme
  13. ;║   (this is an official publication by microsoft but I don't have it)
  14. ;║
  15. ;║ (c) Walken / IMPACT Studios in 1995 - for publication in Imphobia #10
  16. ;╚════════════════════════════════════════════════════════════════════════════
  17.  
  18. ;│ Legal stuff :
  19. ;│ This document can be copyed only when unmodified and in its entirety.
  20. ;│ Commercial use - including commercial distribution or use in commercial
  21. ;│   software - is strictly prohibited without the written permission
  22. ;│   of the author.
  23. ;│ The author excludes any and all implied warranties, including warranties
  24. ;│   of merchantability and fitness for a particular purpose. The author
  25. ;│   should have no liability for special, incidental, or consequential
  26. ;│   damages arising out or resulting from the use or modification of this
  27. ;│   source code.
  28. ;└────────────────────────────────────────────────────────────────────────────
  29.  
  30. ;║ You can contact the author at the following address :
  31. ;║ Walken / IMPACT Studios
  32. ;║ Michel LESPINASSE - 18 rue Jean Giono - 80090 Amiens - FRANCE
  33. ;╚════════════════════════════════════════════════════════════════════════════
  34.  
  35.     .data
  36. import_buffer df 1
  37. device_EMMXXXX0 db 'EMMXXXX0',0    ;EMM device driver name
  38. EMS_handle_name db '■WaLKeN■'
  39. nb_XMS_handle dw 0
  40. nb_available_memory dw 0
  41. native_V86 db 0        ;system mode 0=real 1=V86
  42. local_A20 db 0            ;A20 line touched by XMS 0=no 1=yes
  43. EMS_alloc db 0            ;EMS handle allocated 0=no 1=yes
  44. no_native db 0            ;running with CPU mode <> system mode 0=no 1=yes
  45. flat_enabled db 0        ;running in FRM 0=no 1=yes
  46. NMI_state_touched db 0    ;touched NMI state 0=no 1=yes
  47. int15_hook db 0        ;hooked int 15 0=no 1=yes
  48.  
  49. ptr_GDT label fword
  50.     dw 39,o dgroup:GDT,0,0
  51. GDT dw 4 dup(0)            ;NULL selector
  52.     dw 0ffffh,0,9a00h,0        ;_text selector
  53.     dw 0ffffh,0,9200h,0        ;data16 selector
  54.     dw 4 dup(0)            ;unused
  55.     dw 0ffffh,0,9200h,8fh    ;data32 selector
  56. _text_selector=8
  57.  
  58. ptr_IDT_native label fword
  59.     dw 3ffh,0,0,0
  60. ptr_IDT_flatreal label fword
  61.     dw 3ffh,offset ds:IDT_flatreal,0,0
  62.  
  63. ext_mem_move dd 1024
  64.     dw 0
  65.     dd buffer_mem_move
  66.     dw ?
  67.     dd ?
  68.  
  69. msg_GEMMIS db "GEMMIS protocol denyes access to the real mode$"
  70. msg_no_GEMMIS db "GEMMIS protocol not available$"
  71. msg_bad_GEMMIS db "GEMMIS data anomaly$"
  72. msg_EMM4 db "Your EMM is too old, you'll need EMS 4.0 or higher$"
  73. msg_XMS3 db "Your XMS is too old, you'll need XMS 3.0 or higher$"
  74. msg_hook db "XMS driver hook does not follow XMS 3.0 standard$"
  75. msg_a20 db "Cannot enable the A20 gate$"
  76. msg_XMS_alloc db "XMS memory allocation error$"
  77. msg_EMS_alloc db "EMS memory allocation error$"
  78. msg_fragment db "High memory is fragmented in more than 256 blocks$"
  79. msg_nomem db "Not enough free memory$"
  80. msg_badmem db "Memory allocation error$"
  81. msg_verify_pages db "Cannot verify allocated pages$"
  82. msg_error_pages db "Error in allocated pages$"
  83. msg_CPU db "You'll need a 386 or better to run this program$"
  84. msg_V86_no_XMS db "V86 mode with RAW environment is not supported$"
  85. msg_v86 db "unable to switch to V86 mode for interrupts$"
  86.  
  87. memory_manager_name db 40 dup(' '),'$'
  88.  
  89.     .data?
  90. buffer_mem_move db 1024 dup(?)
  91. available_memory_table dd 257 dup(?,?)
  92. XMS_handle dw 256 dup(?)
  93. EMS_handle dw ?
  94. EMS_size dw ?
  95. modeswitch dd ?
  96. himem_driver dd ?
  97. XMS_hook_base dd ?
  98. XMS_hook_addr dd ?
  99. old_int15 dd ?
  100. exit_msg dw ?
  101. XMS_hook_jmpval db ?
  102. NMI_state db ?
  103.  
  104.     .code
  105.     .486p
  106.  
  107.     ;****************************************;
  108.     ;* memory manager init / alloc function *;
  109.     ;****************************************;
  110.  
  111. mem32_init:
  112.     push cs
  113.     pop ds
  114.  
  115. ;* test proc >= 386
  116.     mov dx,o msg_CPU
  117.     pushf
  118.     pop ax
  119.     or ah,0f0h
  120.     push ax
  121.     popf
  122.     pushf
  123.     pop ax
  124.     and ah,0f0h
  125.     jnz no_immediate_exit    ;long jz instruct not supported on the 286
  126.     jmp immediate_exit
  127. no_immediate_exit:
  128.  
  129. ;* test proc >= 486, include it if your proggy does not support 386 processor
  130. ;    pushfd
  131. ;    pop eax
  132. ;    mov ebx,eax
  133. ;    xor eax,40000h
  134. ;    push eax
  135. ;    popfd
  136. ;    pushfd
  137. ;    pop eax
  138. ;    xor eax,ebx
  139. ;    jz immediate_exit    ;it's a 386
  140. ;    push ebx
  141. ;    popfd
  142.  
  143. ;* test V86 mode
  144.     smsw ax
  145.     test al,1
  146.     jz no_V86
  147.     inc native_V86
  148.  
  149. ;* windows fake init
  150.     mov exit_msg,o msg_GEMMIS
  151.     call open_ouinedoze
  152.  
  153. ;* test EMS driver
  154.     mov exit_msg,o msg_no_GEMMIS
  155.     mov ax,3d00h
  156.     mov dx,o device_EMMXXXX0
  157.     int 21h            ;open handle
  158.     jc exitmsg
  159.     mov bx,ax
  160.     mov ax,4400h
  161.     int 21h            ;get device information
  162.     jc exitmsg
  163.     not dx
  164.     test dx,4080h
  165.     jnz exitmsg
  166.     mov ax,4407h
  167.     int 21h            ;get output status
  168.     jc exitmsg
  169.     inc al
  170.     jnz exitmsg
  171.     mov ah,3eh
  172.     int 21h            ;close handle
  173.  
  174. ;* test EMS version >= 4.0
  175.     mov ah,46h
  176.     int 67h            ;get EMM version
  177.     mov dx,o msg_EMM4
  178.     or ah,ah
  179.     jnz exit
  180.     cmp al,40h
  181.     jb exit
  182.  
  183. no_V86:
  184. ;* test XMS driver
  185.     mov ax,4300h
  186.     int 2fh            ;XMS install test
  187.     cmp al,80h
  188.     jne no_xms
  189.     mov ax,4310h        ;get XMS call adress
  190.     int 2fh
  191.     mov w himem_driver,bx
  192.     mov w himem_driver+2,es
  193.  
  194. ;* test XMS version >= 3.0
  195.     push bx
  196.     xor ax,ax
  197.     call himem_driver    ;get XMS version
  198.     mov dx,o msg_XMS3
  199.     cmp ah,3
  200.     jb exit
  201.     pop bx
  202.  
  203. ;* XMS hook locate (code from XMS 3.0 specification)
  204. locate_xms_hook:
  205.     mov dx,o msg_hook
  206.     mov cx,w es:[bx]
  207.     cmp cl,0ebh        ;short jump
  208.     je found_xms_hook
  209.     cmp cl,0eah        ;far jump
  210.     jne exit
  211.     les bx,d es:[bx+1]
  212.     jmp locate_xms_hook
  213. found_xms_hook:
  214.     mov eax,d es:[bx+2]
  215.     and eax,0ffffffh
  216.     xor eax,909090h    ;3x nop
  217.     jnz exit
  218.     mov al,ch
  219.     mov XMS_hook_jmpval,al
  220.     add al,2
  221.     add ax,bx
  222.     mov w XMS_hook_base,bx
  223.     mov w XMS_hook_base+2,es
  224.     mov w XMS_hook_addr,ax
  225.     mov w XMS_hook_addr+2,es
  226.  
  227. ;* enable A20 gate (XMS)
  228.     push bx
  229.     mov ah,5
  230.     call himem_driver    ;local enable A20
  231.     mov dx,o msg_a20
  232.     dec ax
  233.     jnz exit
  234.     pop bx
  235.     inc local_A20
  236.  
  237. ;* XMS hook install
  238.     cli
  239.     mov b es:[bx],0eah    ;far jump
  240.     mov w es:[bx+1],o cs:XMS_hook
  241.     mov w es:[bx+3],cs
  242.     sti
  243.  
  244. ;* init check pages buffer
  245.     push cs
  246.     pop es
  247.     mov di,o cs:buffer_mem_move
  248.     mov cx,64
  249.     call fill_check_page
  250.  
  251. ;* XMS allocate
  252.     xor edi,edi
  253. XMS_alloc:
  254.     mov exit_msg,o msg_XMS_alloc
  255.     xor bl,bl            ;grumbl
  256.     mov ah,8
  257.     call himem_driver    ;query free XMS memory
  258.     or ax,ax            ;grumbl
  259.     jz XMS_allocated
  260.     or bl,bl            ;grumbl
  261.     jnz XMS_allocated
  262.     add ax,64
  263.     mov dx,ax
  264. XMS_alloc_block:
  265.     push dx
  266.     mov ah,9
  267.     call himem_driver    ;allocate XMS block
  268.     dec ax
  269.     jz XMS_block_allocated
  270.     pop dx
  271.     sub dx,64
  272.     jbe XMS_allocated
  273.     jmp XMS_alloc_block
  274. XMS_block_allocated:
  275.     mov XMS_handle[edi*2],dx
  276.     mov d ext_mem_move[12],0
  277.     mov w ext_mem_move[10],dx
  278.     inc di
  279.     mov nb_XMS_handle,di
  280.     mov ah,0ch
  281.     call himem_driver    ;lock XMS block
  282.     dec ax
  283.     jnz exitmsg
  284.  
  285. ;* write to the XMS block for further check of allocated pages
  286.     mov exit_msg,o msg_verify_pages
  287.     pop cx
  288.     push cx
  289.     push bx
  290. test_XMS_block:
  291.     mov ah,0bh
  292.     mov si,o ext_mem_move
  293.     call himem_driver    ;copy to XMS block
  294.     dec ax
  295.     jnz exitmsg
  296.     add d ext_mem_move[12],1024
  297.     loop test_XMS_block
  298.     pop bx
  299.  
  300. ;* save adress of the XMS block
  301.     xor eax,eax
  302.     pop ax
  303.     shl eax,10
  304.     shl edx,16
  305.     mov dx,bx
  306.     add eax,edx
  307.     mov available_memory_table[edi*8-8],edx
  308.     mov available_memory_table[edi*8-4],eax
  309.     cmp di,256
  310.     jb XMS_alloc
  311. XMS_allocated:
  312.     mov nb_available_memory,di
  313.  
  314. ;* if not native V86 mode skip EMS & GEMMIS
  315.     cmp native_V86,0
  316.     jz flat
  317.  
  318. ;* EMS allocate & set handle name
  319.     mov exit_msg,o msg_EMS_alloc
  320.     mov ah,42h
  321.     int 67h            ;get unallocated page count
  322.     or ah,ah
  323.     jnz exitmsg
  324.     or bx,bx
  325.     jz EMS_allocated
  326.     mov EMS_size,bx
  327.     mov ah,43h
  328.     int 67h            ;allocate pages
  329.     or ah,ah
  330.     jnz exitmsg
  331.     inc EMS_alloc
  332.     mov EMS_handle,dx
  333.     mov ax,5301h
  334.     mov si,o ds:EMS_handle_name
  335.     int 67h            ;set handle name
  336.     or ah,ah
  337.     jnz exitmsg
  338.  
  339. ;* write to the EMS block for further check of allocated pages
  340.     mov exit_msg,o msg_verify_pages
  341.     xor ecx,ecx
  342.     mov cx,bx
  343.     mov ah,47h
  344.     int 67h            ;save page map
  345.     or ah,ah
  346.     jnz exitmsg
  347.     mov ah,41h
  348.     int 67h            ;get page frame address
  349.     or ah,ah
  350.     jnz exitmsg
  351.     mov es,bx
  352. check_EMS_page:
  353.     mov ax,4400h
  354.     lea bx,[ecx-1]
  355.     int 67h            ;map handle page
  356.     or ah,ah
  357.     jnz exitmsg
  358.     xor di,di
  359.     push cx
  360.     mov cx,1024
  361.     call fill_check_page
  362.     pop cx
  363.     loop check_EMS_page
  364.     mov ah,48h
  365.     int 67h            ;restore page map
  366.     or ah,ah
  367.     jnz exitmsg
  368. EMS_allocated:
  369.  
  370. ;* GEMMIS IOCTL
  371.     mov exit_msg,o ds:msg_no_GEMMIS
  372.     mov ax,3d00h
  373.     mov dx,offset cs:device_EMMXXXX0
  374.     int 21h            ;open device
  375.     jc exitmsg        ;device does not exist
  376.     mov bx,ax
  377.     mov ax,4402h
  378.     mov cx,6
  379.     mov dx,offset ds:import_buffer
  380.     int 21h            ;IOCTL read
  381.     jc exitmsg        ;cannot read device
  382.     cmp ax,cx
  383.     jne exitmsg        ;cannot read device
  384.     mov ah,3eh
  385.     int 21h            ;close device
  386.  
  387. ;* test GEMMIS version >= 1.0
  388.     cmp b import_buffer+4,1
  389.     jb exitmsg
  390.  
  391. ;* real mode switch
  392.     mov exit_msg,o ds:msg_GEMMIS
  393.     call switch_to_real
  394.  
  395. ;* flat mode switch
  396.     call first_enable_flat
  397.  
  398. ;* GEMMIS data decode : find physical addresses allocated to the EMS block
  399.     mov exit_msg,o msg_bad_GEMMIS
  400.     xor ax,ax
  401.     mov es,ax
  402.     mov esi,d import_buffer
  403.     add esi,397
  404.     movzx ecx,b es:[esi-2]
  405.     shl cx,4
  406.     add esi,ecx        ;skip UMB frame descriptors
  407.     push esi            ;here es:esi points to first EMS handle info record
  408.     cmp EMS_alloc,0
  409.     jz no_EMS_handle
  410.     xor ecx,ecx
  411.     mov cl,es:[esi-1]
  412.     inc cx            ;number of EMS handle info records
  413.     sub esi,16
  414. find_EMS_handle:
  415.     dec cx
  416.     jz exitmsg
  417.     add esi,16
  418.     cmp d es:[esi+2],'LaW■'
  419.     jne find_EMS_handle
  420.     cmp d es:[esi+6],'■NeK'
  421.     jne find_EMS_handle
  422.     mov cx,es:[esi+10]
  423.     mov esi,es:[esi+12]    ;page map for allocated EMS block
  424.     cmp EMS_size,cx
  425.     jne exitmsg
  426.     shl cx,2
  427.     xor edi,edi
  428.     mov di,nb_available_memory
  429.     lods d es:[esi]
  430.     and ax,0f000h
  431.     mov ebx,eax
  432.     jmp contiguous
  433. find_contiguous:
  434.     lods d es:[esi]
  435.     and ax,0f000h
  436.     cmp eax,edx
  437.     je contiguous
  438.     mov available_memory_table[edi*8],ebx
  439.     mov available_memory_table[edi*8+4],edx
  440.     mov dx,o msg_fragment
  441.     inc di
  442.     cmp di,256
  443.     je exit
  444.     mov ebx,eax
  445. contiguous:
  446.     lea edx,[eax+1000h]
  447.     loop find_contiguous
  448.     mov available_memory_table[edi*8],ebx
  449.     mov available_memory_table[edi*8+4],edx
  450.     inc di
  451.     mov nb_available_memory,di
  452. no_EMS_handle:
  453.     pop esi
  454.  
  455. ;* GEMMIS data decode : save memory manager name if version >= 1.11
  456.     mov ax,w import_buffer[4]
  457.     xchg al,ah
  458.     cmp ax,10ah
  459.     jb dont_save_name
  460.     push ax
  461.     movzx cx,b es:[esi-1]    ;number of EMS handle info records to skip
  462.     shl cx,4
  463.     add esi,ecx
  464.     xor cx,cx
  465.     mov cl,b es:[esi+8]
  466.     lea esi,[esi+ecx*8]        ;skip free page entryes
  467.     mov cl,b es:[esi+9]
  468.     lea ecx,[ecx*2+ecx]
  469.     lea esi,[esi+ecx*4]        ;skip XMS handle info records
  470.     xor cx,cx
  471.     mov cl,b es:[esi+10]
  472.     lea esi,[esi+ecx*4+11]    ;skip free UMB info records
  473.     pop ax
  474.     cmp ax,10bh
  475.     ja dont_check_size
  476.     mov edi,d import_buffer
  477.     mov cx,es:[edi+2]
  478.     lea edi,[edi+ecx]
  479.     jb version_110
  480.     sub edi,40
  481. version_110:
  482.     cmp esi,edi
  483.     jne exitmsg
  484.     cmp ax,10ah
  485.     je dont_save_name
  486. dont_check_size:
  487.     mov di,o ds:memory_manager_name
  488.     mov cx,10
  489. copy_name:
  490.     lods d es:[esi]
  491.     mov [di],eax
  492.     add di,4
  493.     loop copy_name
  494. dont_save_name:
  495.  
  496. ;* goto init_return
  497.     jmp init_return
  498.  
  499. no_xms:
  500. ;* exit if native V86 mode and no XMS manager
  501.     mov dx,o msg_V86_no_XMS
  502.     cmp native_V86,0
  503.     jnz exit
  504.  
  505. ;* enable A20 gate (RAW) / this code is from TRAN aka Thomas Pytel
  506.     cli
  507.     xor ax,ax            ;set A20 test segments 0 and 0ffffh
  508.     mov fs,ax
  509.     dec ax
  510.     mov gs,ax
  511.     call enable_A20_test
  512.     jz enable_A20_done
  513.     in al,92h            ;PS/2 A20 enable
  514.     or al,2
  515.     jmp $+2
  516.     jmp $+2
  517.     jmp $+2
  518.     out 92h,al
  519.     call enable_A20_test
  520.     jz enable_A20_done
  521.     call enable_A20_kb_wait    ;AT A20 enable
  522.     jnz wait_enable_A20
  523.     mov al,0d1h
  524.     out 64h,al
  525.     call enable_A20_kb_wait
  526.     jnz wait_enable_A20
  527.     mov al,0dfh
  528.     out 60h,al
  529.     call enable_A20_kb_wait
  530. wait_enable_A20:        ;wait for A20 to enable
  531.     mov cx,800h
  532. loop_wait_enable_A20:
  533.     call enable_A20_test
  534.     jz enable_A20_done
  535.     in al,40h
  536.     jmp $+2
  537.     jmp $+2
  538.     jmp $+2
  539.     in al,40h
  540.     mov ah,al
  541. A20_wait_tick:
  542.     in al,40h
  543.     jmp $+2
  544.     jmp $+2
  545.     jmp $+2
  546.     in al,40h
  547.     cmp al,ah
  548.     je A20_wait_tick
  549.     loop loop_wait_enable_A20
  550.     mov dx,o msg_a20
  551.     jmp exit
  552. enable_a20_done:
  553.     sti
  554.  
  555. ;* get amount of RAW memory / this code is from TRAN aka Thomas Pytel
  556.     mov ah,88h
  557.     int 15h            ;get RAW memory size
  558.     or ax,ax
  559.     jz flat
  560.     movzx eax,ax
  561.     shl eax,10
  562.     add eax,100000h
  563.     mov available_memory_table[4],eax
  564.     les bx,dword ptr fs:[4*19h]
  565.     mov eax,100000h
  566.     cmp dword ptr es:[bx+12h],'SIDV'
  567.     jne no_vdisk_1
  568.     mov eax,dword ptr es:[bx+2ch]
  569.     add eax,0fh
  570.     and eax,0fffff0h
  571. no_vdisk_1:
  572.     cmp dword ptr gs:[13h],'SIDV'
  573.     jne no_vdisk_2
  574.     movzx ebx,w gs:[2eh]
  575.     shl ebx,10
  576.     cmp eax,ebx
  577.     ja no_vdisk_2
  578.     mov eax,ebx
  579. no_vdisk_2:
  580.     cmp eax,available_memory_table[4]
  581.     jae flat
  582.     mov available_memory_table[0],eax
  583.     inc nb_available_memory
  584.  
  585. ;* reserve all available RAW memory
  586.     mov eax,fs:[15h*4]
  587.     mov old_int15,eax
  588.     mov w fs:[15h*4+2],cs
  589.     mov w fs:[15h*4+2],o cs:int15_handler
  590.     inc int15_hook
  591.  
  592. flat:
  593. ;* flat mode switch
  594.     call first_enable_flat
  595.  
  596. init_return:
  597. ;* group contiguous allocated physical memory adresses
  598.     push cs
  599.     pop es
  600.     mov exit_msg,o msg_badmem
  601.     xor ecx,ecx
  602. sort_available_memory:
  603.     mov dx,o msg_nomem
  604.     mov cx,nb_available_memory
  605.     dec cx
  606.     js exit
  607.     jz available_memory_grouped
  608. sort_available_memory_pass:
  609.     mov eax,available_memory_table[ecx*8-8]
  610.     cmp eax,available_memory_table[ecx*8]
  611.     jna available_memory_sorted
  612.     xchg eax,available_memory_table[ecx*8]
  613.     mov available_memory_table[ecx*8-8],eax
  614.     mov eax,available_memory_table[ecx*8-4]
  615.     xchg eax,available_memory_table[ecx*8+4]
  616.     mov available_memory_table[ecx*8-4],eax
  617.     jmp sort_available_memory
  618. available_memory_sorted:
  619.     loop sort_available_memory_pass
  620. group_available_memory:
  621.     mov cx,nb_available_memory
  622.     dec cx
  623.     jz available_memory_grouped
  624. group_available_memory_pass:
  625.     mov eax,available_memory_table[ecx*8-4]
  626.     cmp eax,available_memory_table[ecx*8]
  627.     ja exitmsg
  628.     jb available_memory_block_grouped
  629.     lea di,available_memory_table[ecx*8-4]
  630.     lea si,[di+8]
  631.     mov cx,nb_available_memory
  632.     lea cx,available_memory_table[ecx*8]
  633.     sub cx,si
  634.     rep movsb
  635.     dec nb_available_memory
  636.     jmp group_available_memory
  637. available_memory_block_grouped:
  638.     loop group_available_memory_pass
  639. available_memory_grouped:
  640.  
  641. ;* check allocated pages if not RAW
  642.     cmp local_A20,0
  643.     jz dont_check_pages
  644.     xor ax,ax
  645.     mov es,ax
  646.     xor ecx,ecx
  647.     mov cx,nb_available_memory
  648.     mov dx,o msg_error_pages
  649. check_allocated_pages:
  650.     mov esi,available_memory_table[ecx*8-8]
  651.     mov ebx,available_memory_table[ecx*8-4]
  652.     sub ebx,esi
  653.     shr ebx,4
  654. check_pages:
  655.     lods d es:[esi]
  656.     cmp eax,'PMI■'
  657.     jne exit
  658.     lods d es:[esi]
  659.     cmp eax,' TCA'
  660.     jne exit
  661.     lods d es:[esi]
  662.     cmp eax,'dutS'
  663.     jne exit
  664.     lods d es:[esi]
  665.     cmp eax,'■soi'
  666.     jne exit
  667.     dec ebx
  668.     jnz check_pages
  669.     loop check_allocated_pages
  670. dont_check_pages:
  671.  
  672. ;* install flat real mode interrupt handler
  673.     cmp native_V86,0
  674.     jz no_flatreal_handler
  675.     lidt cs:ptr_IDT_flatreal
  676.     sti
  677. no_flatreal_handler:
  678.  
  679.     ret
  680.  
  681.     ;*************************************************;
  682.     ;* memory manager switch to native mode function *;
  683.     ;*************************************************;
  684.  
  685. mem32_native:
  686.     cmp native_V86,0
  687.     jz no_native_switch
  688.     mov exit_msg,o ds:msg_V86
  689.     cli
  690.     lidt cs:ptr_IDT_native
  691.     call disable_flat
  692.     call switch_to_v86
  693.     jc exitmsg
  694.     call close_ouinedoze
  695. no_native_switch:
  696.     ret
  697.  
  698.     ;****************************************************;
  699.     ;* memory manager switch to flat real mode function *;
  700.     ;****************************************************;
  701.  
  702. mem32_flatreal:
  703.     cmp native_V86,0
  704.     jz no_flatreal_switch
  705.     mov exit_msg,o ds:msg_V86
  706.     call open_ouinedoze
  707.     call switch_to_real
  708.     call enable_flat
  709.     lidt cs:ptr_IDT_flatreal
  710.     sti
  711. no_flatreal_switch:
  712.     ret
  713.  
  714.     ;*********************************************;
  715.     ;* memory manager exit / unallocate function *;
  716.     ;*********************************************;
  717.     ; DS:DX = exit message to display
  718.  
  719. exit:
  720.     mov exit_msg,dx
  721. exitmsg:
  722.  
  723. ;* disable flat mode
  724.     cmp flat_enabled,0
  725.     jz flat_disabled
  726.     pushf
  727.     call disable_flat
  728.     popf
  729. flat_disabled:
  730.  
  731. ;* native mode switch
  732.     cmp no_native,0
  733.     jz native_exit
  734.     call switch_to_v86
  735.     sti
  736. native_exit:
  737.  
  738. ;* restore NMI state
  739.     cmp NMI_state_touched,0
  740.     jz no_NMI_state
  741.     mov al,NMI_state
  742.     out 70h,al        ;restore NMI state
  743. rept 3
  744.     jmp $+2
  745. endm
  746.     in al,71h
  747. no_NMI_state:
  748.  
  749. ;* unallocate RAW
  750.     cmp int15_hook,0
  751.     jz no_int15_hook
  752.     xor ax,ax
  753.     mov es,ax
  754.     mov eax,old_int15
  755.     mov es:[15h*4],eax
  756. no_int15_hook:
  757.  
  758. ;* disable A20 gate (RAW) - not done yet (and not really necessary)
  759.  
  760. ;* EMS unalloc
  761.     cmp EMS_alloc,0
  762.     jz EMS_unallocated
  763.     mov ah,45h
  764.     mov dx,EMS_handle
  765.     int 67h            ;unallocate pages
  766. EMS_unallocated:
  767.  
  768. ;* XMS unalloc
  769.     xor ecx,ecx
  770.     mov cx,nb_XMS_handle
  771.     jcxz XMS_unallocated
  772. XMS_unalloc:
  773.     mov ah,0dh
  774.     mov dx,XMS_handle[ecx*2-2]
  775.     call himem_driver    ;unlock XMS block
  776.     mov ah,0ah
  777.     call himem_driver    ;release XMS block
  778.     loop XMS_unalloc
  779. XMS_unallocated:
  780.  
  781. ;* local disable A20 & XMS hook desinstall
  782.     cmp local_A20,0
  783.     jz no_A20_disable
  784.     mov al,0ebh
  785.     mov ah,XMS_hook_jmpval
  786.     les bx,XMS_hook_base
  787.     cli
  788.     mov d es:[bx+1],90909090h
  789.     mov w es:[bx],ax
  790.     sti
  791.     mov ah,6
  792.     call himem_driver    ;local disable A20
  793. no_A20_disable:
  794.  
  795. ;* windows fake exit
  796.     cmp native_V86,0
  797.     jz no_fake_exit
  798.     call close_ouinedoze
  799. no_fake_exit:
  800.  
  801.     mov dx,exit_msg
  802. immediate_exit:
  803.     mov ah,9
  804.     int 21h            ;display exit message
  805.  
  806.     mov ax,4c00h
  807.     int 21h            ;exit without errorlevel
  808.  
  809.     ;***********************************************;
  810.     ;* memory manager interrupt handling functions *;
  811.     ;***********************************************;
  812.  
  813. IDT_flatreal equ this word        ;flat real mode interrupt table
  814. irpc hex,<0123456789abcdef>
  815. irpc unit,<0123456789abcdef>
  816. dw it&hex&&unit,_text
  817. endm
  818. endm
  819.  
  820. num=0                        ;flat real mode interrupt handlers
  821. irpc hex,<0123456789abcdef>
  822. irpc unit,<0123456789abcdef>
  823. it&hex&&unit:
  824.     push eax
  825.     mov al,num
  826.     jmp it
  827. num=num+1
  828. endm
  829. endm
  830.  
  831. it:
  832.     lidt cs:ptr_IDT_native
  833.     mov cs:automodif_int+1,al
  834.  
  835.     push ebx
  836.     push ecx
  837.     push edx
  838.     push esi
  839.     push edi
  840.     push ebp
  841.     push ds
  842.     push es
  843.     push fs
  844.     push gs
  845.     mov exit_msg,o ds:msg_V86
  846.     call disable_flat
  847.     call switch_to_v86
  848.     jc exitmsg
  849.     call close_ouinedoze
  850.     pop gs
  851.     pop fs
  852.     pop es
  853.     pop ds
  854.     pop ebp
  855.     pop edi
  856.     pop esi
  857.     pop edx
  858.     pop ecx
  859.     pop ebx
  860.     pop eax
  861.     push esp
  862.     movzx esp,sp
  863.     push w ss:[esp+8]        ;flags, tricky !
  864.     popf
  865. automodif_int db 0cdh,0        ;call the old interrupt handler
  866.     pushf
  867.     pop w ss:[esp+8]        ;flags, tricky !
  868.     cli
  869.     pop esp
  870.  
  871.     push eax
  872.     push ebx
  873.     push ecx
  874.     push edx
  875.     push esi
  876.     push edi
  877.     push ebp
  878.     push ds
  879.     push es
  880.     push fs
  881.     push gs
  882.     mov exit_msg,o ds:msg_V86
  883.     call open_ouinedoze
  884.     call switch_to_real
  885.     call enable_flat
  886.     pop gs
  887.     pop fs
  888.     pop es
  889.     pop ds
  890.     pop ebp
  891.     pop edi
  892.     pop esi
  893.     pop edx
  894.     pop ecx
  895.     pop ebx
  896.     pop eax
  897.     lidt cs:ptr_IDT_flatreal
  898.     iret
  899.  
  900.     ;*************************************;
  901.     ;* memory manager internal functions *;
  902.     ;*************************************;
  903.  
  904. first_enable_flat:
  905.     xor eax,eax
  906.     mov ax,cs
  907.     shl eax,4
  908.     add dword ptr ptr_GDT+2,eax
  909.     add dword ptr ptr_IDT_flatreal+2,eax
  910.     mov si,offset cs:GDT
  911.     mov word ptr [si+_text_selector+2],ax
  912.     shr eax,16
  913.     mov byte ptr [si+_text_selector+4],al
  914.     cli
  915.     in al,70h
  916. rept 3
  917.     jmp $+2
  918. endm
  919.     mov ah,al
  920.     in al,71h
  921. rept 3
  922.     jmp $+2
  923. endm
  924.     mov al,ah
  925.     mov NMI_state,al
  926.     inc NMI_state_touched
  927.     or al,80h
  928.     out 70h,al        ;disable NMI
  929. rept 3
  930.     jmp $+2
  931. endm
  932.     in al,71h
  933.  
  934. enable_flat:
  935.     pushf
  936.     cli
  937.     lgdt fword ptr ptr_GDT
  938.     switch_prot _text,@@pmode
  939. @@pmode:
  940.     mov ax,32
  941.     mov ds,ax
  942.     mov es,ax
  943.     mov fs,ax
  944.     mov gs,ax
  945.     switch_real _text,@@rmode
  946. @@rmode:
  947.     push cs
  948.     pop ds
  949.     popf
  950.     inc flat_enabled
  951.     ret
  952.  
  953. disable_flat:
  954.     cli
  955.     switch_prot _text,@@pmode
  956. @@pmode:
  957.     mov ax,16
  958.     mov ds,ax
  959.     mov es,ax
  960.     mov fs,ax
  961.     mov gs,ax
  962.     switch_real _text,@@rmode
  963. @@rmode:
  964.     push cs
  965.     pop ds
  966.     dec flat_enabled
  967.     ret
  968.  
  969. switch_to_real:
  970.     xor ax,ax
  971.     cli
  972.     call modeswitch
  973.     push cs
  974.     pop ds
  975.     jc exitmsg
  976.     inc no_native
  977.     ret
  978.  
  979. switch_to_v86:
  980.     mov ax,1
  981.     cli
  982.     call cs:modeswitch
  983.     push cs
  984.     pop ds
  985.     mov no_native,0
  986.     ret
  987.  
  988. open_ouinedoze:
  989.     mov ax,1605h
  990.     xor bx,bx
  991.     mov cx,bx
  992.     mov dx,bx
  993.     mov si,bx
  994.     mov di,30bh        ;version number 3.11
  995.     mov ds,bx
  996.     mov es,bx
  997.     int 2fh        ;set device name to "EMMXXXX0" & return entry point addr
  998.     push ds
  999.     push cs
  1000.     pop ds
  1001.     pop ax
  1002.     or cx,cx
  1003.     jnz exitmsg        ;cannot run windows
  1004.     mov w modeswitch+2,ax
  1005.     mov w modeswitch,si
  1006.     or ax,si
  1007.     jz exitmsg        ;modeswitch not available
  1008.     ret
  1009.  
  1010. close_ouinedoze:
  1011.     mov ax,1606h
  1012.     xor dx,dx
  1013.     int 2fh            ;restore device name
  1014.     ret
  1015.  
  1016. fill_check_page:
  1017.     mov eax,'PMI■'
  1018.     stosd
  1019.     mov eax,' TCA'
  1020.     stosd
  1021.     mov eax,'dutS'
  1022.     stosd
  1023.     mov eax,'■soi'
  1024.     stosd
  1025.     loop fill_check_page
  1026.     ret
  1027.  
  1028. XMS_hook:
  1029.     jmp $+5
  1030.     nop
  1031.     nop
  1032.     nop
  1033.     cmp al,3
  1034.     jb @@XMS_okay
  1035.     cmp al,6
  1036.     ja @@XMS_okay
  1037.     mov ax,1
  1038.     retf                ;disable A20 control functions
  1039. @@XMS_okay:
  1040.     jmp cs:XMS_hook_addr
  1041.  
  1042. int15_handler:
  1043.     cmp ah,88h
  1044.     je reserve_high_memory
  1045.     jmp old_int15
  1046. reserve_high_memory:
  1047.     xor ax,ax
  1048.     iret
  1049.  
  1050. enable_A20_kb_wait:        ;wait for safe to write to 8042
  1051.     xor cx,cx
  1052. loop_enable_A20:
  1053.     jmp $+2
  1054.     jmp $+2
  1055.     jmp $+2
  1056.     in al,64h
  1057.     test al,2
  1058.     loopnz loop_enable_A20
  1059.     ret
  1060.  
  1061. enable_A20_test:        ;test for enabled A20
  1062.     mov al,fs:[0]
  1063.     mov ah,al
  1064.     not al
  1065.     xchg al,gs:[10h]
  1066.     cmp ah,fs:[0]
  1067.     mov gs:[10h],al
  1068.     ret
  1069.  
  1070.     ;* init
  1071.     ; switch natif
  1072.     ; message
  1073.     ; [switch frm]
  1074.     ; deinit / release
  1075.     ;* retour
  1076.